package com.example.loginserver.filter;

import com.example.loginserver.domain.SysUser;
import com.example.loginserver.utils.JwtUtils;
import com.fasterxml.jackson.databind.DeserializationConfig;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import io.jsonwebtoken.Claims;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.annotation.Resource;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;

import static com.example.loginserver.domain.Constant.AUTH_TOKEN_PREFIX;

@Slf4j
public class TokenFilter extends BasicAuthenticationFilter {


    private final RedisTemplate<String, String> redisTemplate;

    public TokenFilter(AuthenticationManager authenticationManager, RedisTemplate<String, String> redisTemplate) {
        super(authenticationManager);
        this.redisTemplate = redisTemplate;
    }

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {

        String auth_token = request.getHeader("auth_token");

        if (!StringUtils.hasLength(auth_token)) {

            filterChain.doFilter(request, response);

            return;
        }

        Claims claims = JwtUtils.parseToken(auth_token);

        String redis_key = AUTH_TOKEN_PREFIX + claims.getSubject();

        String principal = redisTemplate.opsForValue().get(redis_key);

        if (!StringUtils.hasLength(principal)) {
            filterChain.doFilter(request, response);
            return;
        }

        ObjectMapper objectMapper = new ObjectMapper();

        objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES,false);

        JsonNode node = objectMapper.readTree(principal);


        List<String> authorities = node.withArray("authorities").findValues("authority").stream().map(JsonNode::asText).collect(Collectors.toList());

        String username = node.findValue("username").asText();


        UserDetails user = new SysUser(0L,username,authorities);

        Authentication authenticationToken = new UsernamePasswordAuthenticationToken(user, null, user.getAuthorities());
        SecurityContextHolder.getContext().setAuthentication(authenticationToken);
        log.info("redis中的用户：{}", principal);

        filterChain.doFilter(request, response);
    }
}
